package software;

import java.io.*;
import java.util.Random;

public class OperationBase {
	static final int UPPER = 100;	//测试时选择如10
	static final int LOWER = 0;
	
	private BinaryOperation[][] addbase;
	private BinaryOperation[][] subbase;
	private BinaryOperation[][] bopbase;
	
	public BinaryOperation[][] getAdditionBase() {
		return addbase;
	}
	public BinaryOperation[][] getSubstractBase() {
		return subbase;
	}
	public BinaryOperation[][] getOperationBase() {
		return bopbase;
	}
	OperationBase(){
		produceAdditionBase();
		produceSubstractBase();
		// 先完成加减法算式基，才能构造混合算式基
		produceBinaryOperationBase();
	}
	
	
	private void produceAdditionBase(){
		addbase = new AdditionOperation[UPPER+1][UPPER+1]; 
		AdditionOperation ao;
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (i+j<=UPPER){
					ao = new AdditionOperation(i,j);
					addbase[i][j]=ao;
				}
			}
		}
	}
	
	
	// 左下角的减法三角形， i-j
	private void produceSubstractBase(){
		subbase = new SubstractOperation[UPPER+1][UPPER+1]; 
		SubstractOperation so;
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (i >= j){
					so = new SubstractOperation(i,j);
					subbase[i][j]=so;
				}
			}
		}
	}
	
	private void produceBinaryOperationBase(){
		bopbase = new BinaryOperation[UPPER+1][UPPER+1]; 
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){  // 左上角，是加法算式
				if (i+j<=UPPER){
					bopbase[i][j] = addbase[i][j];
				}else {                    // 左下角，是减法算式，转成右下角的
					// 减法的算式变成：0≤i, j≤UPPER and 0≤i(UPPER-j)≤UPPER，
					bopbase[i][j] = subbase[i][UPPER-j];
					// System.out.println("------["+i+","+j+"] ="+bopbase[i][j]);
				}
			}
		}
	}
	
	private Exercise generateExercise(int count,BinaryOperation[][] base){
		//当心：没有检查count的范围！可能引起异常，0 < count 且不能超过算式基中算式的总数
		// 混合算式的数量：(UPPER+1)*(UPPER+1)
		BinaryOperation anOperation;
		Exercise anExercise = new Exercise();	
		Random random = new Random();
		int row, column;	
		while (count > 0 ){								
			do {
				row = random.nextInt(UPPER+1);	
				column = random.nextInt(UPPER+1);
				anOperation = base[row][column];
			} while (anOperation == null || anExercise.contains(anOperation));
			anExercise.add(anOperation);
			// System.out.println(""+ anExercise.length()+"\t"+anOperation.fullString());
			count--;
		}
		return anExercise;
	}
	
	public Exercise generateAdditionExercise( int operationCount){
		//当心：没有检查operationCount的范围！可能引起异常	
		if(operationCount>(addbase.length+1)*addbase.length/2) {
			operationCount=(addbase.length+1)*addbase.length/2;
		}
		return generateExercise(operationCount,addbase);	
	}
	public Exercise generateSubtractExercise( int operationCount){
		//当心：没有检查operationCount的范围！可能引起异常	
		if(operationCount>(subbase.length+1)*subbase.length/2) {
			operationCount=(subbase.length+1)*subbase.length/2;
		}
		return generateExercise(operationCount,subbase);	
	}
	// 把加法基于减法基合并在一个二维数组OperationBase时，使用此方法。
	public Exercise generateExercise( int operationCount){
		//当心：没有检查operationCount的范围！可能引起异常	
		if(operationCount>bopbase.length*bopbase.length) {
			operationCount=bopbase.length*bopbase.length;
		}
		return generateExercise(operationCount,bopbase);	
	}
	
	public void displayBase(BinaryOperation[][] base){
		for (BinaryOperation[] row: base){
			for (BinaryOperation operation:row){
				if (operation != null ){
					System.out.print(operation.asString()+"\t");
				}
			}
			System.out.println();
		}
	}
	
	public void saveCSVAdditionBase(String fileName) {
		saveCSVBase(addbase, fileName+"_AddBase_"+UPPER+".txt");
	}
	public void saveCSVSubtractBase(String fileName) {
		saveCSVBase(addbase, fileName+"_SubBase_"+UPPER+".txt");
	}
	public void saveCSVOperationBase(String fileName) {
		saveCSVBase(addbase, fileName+"_BopBase_"+UPPER+".txt");
	}
	private void saveCSVBase(BinaryOperation[][] base, String fileName){
		File wfile = new File(fileName);
		Writer out;
		try{
			out = new FileWriter(wfile, true);
			for (BinaryOperation[] row: base){
				for (BinaryOperation operation:row){
					if (operation != null ){
						out.write(operation.toString()+",");
					}
				}
				out.write("\n");			
			}
			out.flush();
			out.close();
		}
		catch(IOException e){
			System.out.println("ERROR: "+e);
		}
	}
	
}
